package bank;
import java.util.Enumeration;
import java.util.Hashtable;

import branch_access.Manager;

import mware_lib.NameService;
import mware_lib.ObjectBroker;

/**
 * Class for the Manager of the Bank
 *
 */
public class Bank extends Manager {
	private static final long serialVersionUID = 9044288048691033565L;
	private Hashtable<String, Account> AccountTable; // intern List of the Accounts
	private Hashtable<String, String> OwnerTable; // intern List of the Account owners
	
	private String AccountPrefix; // fuer bankuebergreifend eindeutige Konto-IDs
	
	private int AccountCounter;  // Account Counter
	private Object NumberFormatted[] = new Object[1]; // zum Formatieren
	
	private static NameService nameSvc;
	
	
	/**
	 * Konstruktor.
	 * 
	 * @param accountPrefix Prefix for (bankuebergreifend) unique Account-IDs
	 */
	public Bank(String accountPrefix) {
		AccountTable = new Hashtable<String, Account>();
		OwnerTable = new Hashtable<String, String>();
		
		//initializing Account Counter
		AccountCounter = 999;  
		
		//Prefix for Account-IDs of this Bank
		AccountPrefix = accountPrefix;
	}
	
	/**
	 * returns the next available Account-ID.
	 * 
	 * @return new Account-ID
	 */
	private String getNextAvailID() {
		NumberFormatted[0] = new Integer(AccountCounter++);
		return AccountPrefix+String.format("%010d", NumberFormatted);
	}
	
	/**
	 * Creates a new Account and saves it into the displayed Lists.
	 * 
	 * @return New Account-Object
	 */
	private Account setupAccount(String ownerName) {
		// new ID
		String newID = getNextAvailID();
		
		// new Account
		Account newAccount = new Account(newID);
		// ...into the lists
		AccountTable.put(newID, newAccount);
		OwnerTable.put(newID, ownerName);
		return newAccount;
	}
	
	@Override
	public String createAccount(String ownerName) {
		// New Account-Object
		Account newAccount = setupAccount(ownerName);
		// ID of the new Account
		String newID = newAccount.getID();

		/* -----------------------------------
		 * TODO: Log in the Namensdienst 
		 */
		try{
			nameSvc.rebind(newAccount, newID);
		}catch(Exception e){
			AccountTable.remove(newID);
			OwnerTable.remove(newID);
			System.err.println("Problem with creation of the new account");
			return newID;
		}
		/*
		 * -----------------------------------
		 */
		
		System.out.println("New account created");
		return newID;
	}

	/**
	 * returns Lists with current Account States
	 * (Will be used by the GUI)
	 * 
	 * @return List with Account States.
	 */
	public Hashtable<String, Double> getBalanceList() {
		Hashtable<String, Double> balanceList = new Hashtable<String, Double>();
		
		Enumeration<String> keys = AccountTable.keys();
		while (keys.hasMoreElements()) {
			String key = keys.nextElement();
			balanceList.put(key, new Double(AccountTable.get(key).getBalance()));
		}
		return balanceList;
	}

	/**
	 * returns Lists with the names of the Accounts owners
	 * (Will be used by the GUI)
	 * 
	 * @return List with the Names of the Accounts owners.
	 */
	public Hashtable<String, String> getOwnerList() {
		return OwnerTable;
	}


		
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String myName;  // for the Title bar
		String myPrefix = "A";   // for the Account-IDs
//		args=new String[3];
//		args[0]="Bank";
//		args[1]="localhost";
//		args[2]="1777";
		String regEx = "([a-zA-Z0-9 \t\\.\\-]*)";
		String regExPort = "([0-9]*)";

		if (args.length>0 && !args[0].equals("--help") 
				&& args[0].matches(regEx) && args[1].matches(regEx) && args[2].matches(regExPort)) {
			myName = args[0];
			
			// Manager
			Bank myBank = new Bank(myPrefix);
			
			// GUI
			BankWindow myGUI = new BankWindow(myName, myBank);
			myGUI.setVisible(true);
			new Thread(myGUI).start();  // Update of the Thread of the GUI
			
			/* ---------------------------------------
			 * TODO: Save/Log the Manager in the Namensdienst
			 */
			ObjectBroker objBroker = ObjectBroker.getBroker(args[1], Integer.parseInt(args[2]));
			nameSvc = objBroker.getNameService();
			try
			{
				nameSvc.rebind(myBank, args[0]);
			}
			catch(Exception e)
			{
				System.err.println(e.getMessage());
				System.exit(-1);
			}
			/* 
			 * --------------------------------------- 
			 */
			
		} else {
			System.err.println("Usage: java bank.Bank <name> <name-service-host> <name-service-port>");
			System.err.println("Host and name must contain only the characters 'A'...'Z','a'...'z','1'...'9','.','-' and Blanks");
			System.err.println("Port must contain only the characters '1'...'9'");
		}
	}

	@Override
	public boolean removeAccount(String accountID) {
		if((AccountTable.remove(accountID)) != null 
				&& (OwnerTable.remove(accountID) != null))
		{
			return true;
		}
		return false;
	}
}
